home *** CD-ROM | disk | FTP | other *** search
- /*
- * rcString.C - reference counted string class.
- *
- * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
- * Igor Metz (metz@iam.unibe.ch)
- * University of Berne, Switzerland
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- */
-
- #ifdef AMIGA_GCC
- #include "string.h"
- #endif
-
- #include <iostream.h>
- #include "rcString.h"
- #include "Error.h"
-
- //___________________________________________________________ rcStringRep
- //
- // reference counted rcString representation
-
- class rcStringRep
- {
- friend class rcString;
-
- public:
- rcStringRep(char);
- rcStringRep(const char*);
- ~rcStringRep();
-
- private:
- char* str;
- int len;
- int count;
-
- private:
- rcStringRep(_Char_p_*);
- void ref();
- void deref();
- };
-
- inline rcStringRep::rcStringRep(char c) {
- str = new char[2]; str[0] = c; str[1] = '\0';
- count = len = 1;
- }
-
- inline rcStringRep::rcStringRep(const char* s) {
- len = strlen(s);
- str = new char[len+1];
- strcpy(str, s);
- count = 1;
- }
-
- inline rcStringRep::~rcStringRep() {
- delete [] str;
- }
-
- inline rcStringRep::rcStringRep(_Char_p_* r) {
- str = *r; count = 1; len = strlen(str);
- }
-
- inline void rcStringRep::ref() {
- count++;
- }
-
- inline void rcStringRep::deref() {
- if (--count <= 0) delete this;
- }
-
- //___________________________________________________________ rcString
-
- // constructors and destructors
-
- rcString::rcString() {
- rep = new rcStringRep("");
- }
-
- rcString::rcString(char c) {
- rep = new rcStringRep(c);
- }
-
- rcString::rcString(const char* s) {
- rep = new rcStringRep(s);
- }
-
- rcString::rcString(const rcString &s) {
- s.rep->ref(); rep = s.rep;
- }
-
- rcString::rcString(_Char_p_* r) {
- rep = new rcStringRep(r);
- }
-
- rcString::~rcString() {
- rep->deref();
- }
-
- // status reports
-
- unsigned rcString::length() const {
- return rep->len;
- }
-
- int rcString::empty() const {
- return rep->len == 0;
- }
-
- const char* rcString::chars() const {
- return rep->str;
- }
-
- rcString::operator const char*() const {
- return rep->str;
- }
-
- // element extraction and substring
-
- char& rcString::operator[](unsigned i)
- {
- if (i>=length())
- Error(ERR_PANIC, "rcString::operator[] index out of range");
- /*
- * Copy on write!
- */
- if (rep->count > 1) {
- rep->deref();
- rep = new rcStringRep(rep->str);
- }
-
- return rep->str[i];
- }
-
- char rcString::operator[](unsigned i) const
- {
- if (i>=length())
- Error(ERR_PANIC, "rcString::operator[] index out of range");
-
- return rep->str[i];
- }
-
- rcString rcString::operator()(unsigned i, unsigned j)
- {
- if (j<i || i>=length() || j>=length())
- Error(ERR_PANIC, "rcString::operator() index out of range");
-
- char* buf = new char[j-i+1];
- strncpy(buf, rep->str+i, j-i);
- buf[j-i] = '\0';
-
- return rcString(&buf);
- }
-
- // assignment
-
- const rcString& rcString::operator=(char c)
- {
- rep->deref();
- rep = new rcStringRep(c);
-
- return *this;
- }
-
- const rcString& rcString::operator=(const char* s)
- {
- rep->deref();
- rep = new rcStringRep(s);
-
- return *this;
- }
-
- const rcString& rcString::operator=(const rcString& s)
- {
- s.rep->ref();
- rep->deref();
- rep = s.rep;
-
- return *this;
- }
-
- // comparison operators
-
- int rcString::operator==(const rcString& s) const {
- return (strcmp(rep->str, s.rep->str) == 0);
- }
-
- int rcString::operator==(const char* s) const {
- return (strcmp(rep->str, s) == 0);
- }
-
- int rcString::operator!=(const rcString& s) const {
- return (strcmp(rep->str, s.rep->str) != 0);
- }
-
- int rcString::operator!=(const char* s) const {
- return (strcmp(rep->str, s) != 0);
- }
-
- int rcString::operator<(const rcString& s) const {
- return (strcmp(rep->str, s.rep->str) < 0);
- }
-
- int rcString::operator<=(const rcString& s) const {
- return (strcmp(rep->str, s.rep->str) <= 0);
- }
-
- int rcString::operator>(const rcString& s) const {
- return (strcmp(rep->str, s.rep->str) > 0);
- }
-
- int rcString::operator>=(const rcString& s) const {
- return (strcmp(rep->str, s.rep->str) >= 0);
- }
-
- // concatenation
-
- rcString operator+(const rcString& x, const char* y)
- {
- char* buf = new char[x.length() + strlen(y) + 1];
- strcpy(buf, x.chars());
- strcat(buf, y);
-
- return rcString(&buf); // call the private constructor
- }
-
- rcString operator+(const char* x, const rcString& y)
- {
- char* buf = new char[strlen(x) + y.length() + 1];
- strcpy(buf, x);
- strcat(buf, y.chars());
-
- return rcString(&buf); // call the private constructor
- }
-
- rcString operator+(const rcString& x, const rcString& y)
- {
- char* buf = new char[x.length() + y.length() + 1];
- strcpy(buf, x.chars());
- strcat(buf, y.chars());
-
- return rcString(&buf); // call the private constructor
- }
-
- // stream operators
-
- ostream& operator<<(ostream& os, const rcString& s)
- {
- return os << s.chars();
- }
-